In [3]:
import pylibczi
import pathlib
from PIL import Image
import numpy as np

Reading a portion of a large multiscene image

Load a 1.13 TB file

In [4]:
pth = pathlib.Path('/allen/aics/assay-dev/MicroscopyData/Sue/2019/20190610/20190610_S02-02.czi')
pth.stat().st_size/(1024*1024*1024)
Out[4]:
1128.8392663002014
In [5]:
czi = pylibczi.CziFile(pth)
/allen/aics/assay-dev/MicroscopyData/Sue/2019/20190610/20190610_S02-02.czi

Get the shape of the data in the file

In [6]:
czi.dims()
Out[6]:
{'Z': (0, 70), 'C': (0, 2), 'T': (0, 146), 'S': (0, 12), 'B': (0, 1)}

Load the image slice I want

In [7]:
img, shp = czi.read_image(S=4, T=11, C=0, Z=30) 

The shp object gives the order and size of the dimensions of the numpy.ndarray

In [8]:
shp
Out[8]:
[('S', 1), ('T', 1), ('C', 1), ('Z', 1), ('Y', 1300), ('X', 1900)]
In [9]:
img.shape
Out[9]:
(1, 1, 1, 1, 1300, 1900)
In [10]:
d_img = img[0,0,0,0, :, :]

Normalize the image so it displays sensibly

In [11]:
norm_by = np.percentile(d_img, [5, 98])
In [12]:
i2 = np.clip((d_img - norm_by[0])/(norm_by[1]-norm_by[0]), 0, 1)*255

Display the image

d_img above will be of the integer type of the native image however after scalling and clipping the image needs to be cast back to an integer

In [13]:
img_disp = Image.fromarray(i2.astype(np.uint8))
img_disp
Out[13]:

Reading a large mosaic file

A mosaic file is an aquisition mode in which the microscope tiles a space to create a large composite image.

Load a 27 GB mosaic file

In [14]:
pTwo = pathlib.Path('~/Data/20190618_CL001_HB01_Rescan_002.czi').expanduser()
pTwo.stat().st_size/(1024*1024*1024)
Out[14]:
27.03977859020233
In [15]:
cziTwo = pylibczi.CziFile(pTwo)
/Users/jamies/Data/20190618_CL001_HB01_Rescan_002.czi

Get the shape of the mosaic file

In [16]:
cziTwo.dims()
Out[16]:
{'C': (0, 5), 'S': (0, 16), 'B': (0, 1)}

Check it is a mosaic file

In [17]:
cziTwo.is_mosaic()
Out[17]:
True

Get the images full shape

x, y is the upper left coorinate image based coordinate system

Read the mosaic file

Note mosaic files as shown above have a Scene index but are not meant to be reassabled using that constraint they internally use an M-Index instead. Consequently when attempting to specify the 2D plane you want lock in all dimensions larger than 1 except scene. The scale_factor below loads a w/10 by h/10 version of the image (ie 1/100th of the original number of pixels).

In [18]:
icOne = cziTwo.read_mosaic(C=1, scale_factor=0.1)
In [19]:
icOne.shape
Out[19]:
(1, 1, 6265, 6998)

Scale and render the mosaic file

In [20]:
itwo = icOne[0,0,:, :]
norm_by = np.percentile(itwo, [5, 98])
itwonorm = np.clip((itwo - norm_by[0])/(norm_by[1]-norm_by[0]), 0, 1)*255
itwonorm_disp = Image.fromarray(itwonorm.astype(np.uint8))
itwonorm_disp
Out[20]:

Read a portion of the mosaic file

Get the full image coordinate system

In [21]:
sze = cziTwo.read_mosaic_size()
(sze.x, sze.y, sze.w, sze.h)
Out[21]:
(-100980, 7341, 69986, 62649)
In [22]:
### read only the upper corner of the full image
In [23]:
rgn = (sze.x, sze.y, int(sze.w/5), int(sze.h/5))
icOne = cziTwo.read_mosaic(C=1, region=rgn, scale_factor=0.1)
In [24]:
itwo = icOne[0,0,:, :]
norm_by = np.percentile(itwo, [5, 98])
itwonorm = np.clip((itwo - norm_by[0])/(norm_by[1]-norm_by[0]), 0, 1)*255
itwonorm_disp = Image.fromarray(itwonorm.astype(np.uint8))
itwonorm_disp
Out[24]:
In [ ]: